package n_log

import (
	"context"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"sync"
)

type Field = zapcore.Field

type Logger interface {
	Debug(msg string, fields ...Field)
	Debugc(context context.Context, msg string)
	Debugf(msg string, args ...interface{})
	Debugfc(context context.Context, msg string, args ...interface{})
	Debugw(msg string, keysAndValues ...interface{}) // s.sweetenFields(context) keysAndValues 键值对
	Debugwc(context context.Context, msg string, keysAndValues ...interface{})
}

var _ Logger = &zapLogger{}

type zapLogger struct {
	zapLogger *zap.Logger
}

func (z zapLogger) Debug(msg string, fields ...Field) {
	z.zapLogger.Debug(msg)
}

func Debug(msg string) {
	defaultLogger.Debug(msg)
}

func (z zapLogger) Debugc(context context.Context, msg string) {
	//TODO implement me
	panic("implement me")
}

func (z zapLogger) Debugf(msg string, args ...interface{}) {
	//TODO implement me
	panic("implement me")
}

func (z zapLogger) Debugfc(context context.Context, msg string, args ...interface{}) {
	//TODO implement me
	panic("implement me")
}

func (z zapLogger) Debugw(msg string, keysAndValues ...interface{}) {
	//TODO implement me
	panic("implement me")
}

func (z zapLogger) Debugwc(context context.Context, msg string, keysAndValues ...interface{}) {
	//TODO implement me
	panic("implement me")
}

var (
	defaultLogger = New(NewOptions())
	mu            = sync.Mutex{}
)

func Logs() *zapLogger {
	return defaultLogger
}

func New(opts *Options) *zapLogger {
	if opts == nil {
		opts = NewOptions()
	}

	// 实例化 zap
	// 设置 zap 默认值
	var zapLevel zapcore.Level
	if err := zapLevel.UnmarshalText([]byte(opts.Level)); err != nil {
		zapLevel = zapcore.InfoLevel
	}

	loggerConfig := zap.Config{
		Level: zap.NewAtomicLevelAt(zapLevel),
		//Development:      true,
		Encoding:         opts.Format,
		EncoderConfig:    zap.NewDevelopmentEncoderConfig(),
		OutputPaths:      opts.OutputPaths,
		ErrorOutputPaths: opts.ErrorOutputPaths,
	}
	// Build() 该方法会根据当前的配置参数，生成一个 *zap.Logger 对象
	// 调用了 zap.AddStacktrace 函数，用于向日志中添加堆栈跟踪信息。
	// 在这里，它会将日志级别设置为 PanicLevel 时，自动添加堆栈跟踪信息。这样，在程序出现 panic 错误时，就可以在日志中查看完整的调用栈信息，方便快速定位问题
	l, err := loggerConfig.Build(zap.AddStacktrace(zapcore.PanicLevel))
	if err != nil {
		panic(err)
	}
	logger := &zapLogger{zapLogger: l.Named(opts.Name)}
	return logger
}

func Init(opt *Options) {
	// 看起来没有问题, 存在并发问题 但是后面可能希望这个全局的 logger 是动态
	mu.Lock()
	defer mu.Unlock()
	defaultLogger = New(opt)
}
